package demo.java.lang.management;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Arrays;

import javax.management.ObjectName;

import org.junit.Test;

import demo.javax.management.ObjectNameDemo;

public class ThreadMXBeanDemo {

    @Test
    public void testThreadMXBean() {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        System.out.println("deadlockedThreads = " + Arrays.toString(deadlockedThreads));
        long[] monitorDeadlockedThreads = threadMXBean.findMonitorDeadlockedThreads();
        System.out.println("monitorDeadlockedThreads = " + Arrays.toString(monitorDeadlockedThreads));
        long[] allThreadIds = threadMXBean.getAllThreadIds();
        System.out.println("allThreadIds = " + Arrays.toString(allThreadIds));
        long currentThreadCpuTime = threadMXBean.getCurrentThreadCpuTime();
        System.out.println("currentThreadCpuTime = " + currentThreadCpuTime);
        long currentThreadUserTime = threadMXBean.getCurrentThreadUserTime();
        System.out.println("currentThreadUserTime = " + currentThreadUserTime);
        int daemonThreadCount = threadMXBean.getDaemonThreadCount();
        System.out.println("daemonThreadCount = " + daemonThreadCount);
        ObjectName objectName = threadMXBean.getObjectName();
        ObjectNameDemo.printObjectName(objectName);
        int peakThreadCount = threadMXBean.getPeakThreadCount();
        System.out.println("peakThreadCount = " + peakThreadCount);
        int threadCount = threadMXBean.getThreadCount();
        System.out.println("threadCount = " + threadCount);
        long totalStartedThreadCount = threadMXBean.getTotalStartedThreadCount();
        System.out.println("totalStartedThreadCount = " + totalStartedThreadCount);
        boolean isCurrentThreadCpuTimeSupported = threadMXBean.isCurrentThreadCpuTimeSupported();
        System.out.println("isCurrentThreadCpuTimeSupported = " + isCurrentThreadCpuTimeSupported);
        boolean isObjectMonitorUsageSupported = threadMXBean.isObjectMonitorUsageSupported();
        System.out.println("isObjectMonitorUsageSupported = " + isObjectMonitorUsageSupported);
        boolean isSynchronizerUsageSupported = threadMXBean.isSynchronizerUsageSupported();
        System.out.println("isSynchronizerUsageSupported = " + isSynchronizerUsageSupported);
        boolean isThreadContentionMonitoringEnabled = threadMXBean.isThreadContentionMonitoringEnabled();
        System.out.println("isThreadContentionMonitoringEnabled = " + isThreadContentionMonitoringEnabled);
        boolean isThreadCpuTimeEnabled = threadMXBean.isThreadCpuTimeEnabled();
        System.out.println("isThreadCpuTimeEnabled = " + isThreadCpuTimeEnabled);
        boolean isThreadCpuTimeSupported = threadMXBean.isThreadCpuTimeSupported();
        System.out.println("isThreadCpuTimeSupported = " + isThreadCpuTimeSupported);
        threadMXBean.resetPeakThreadCount();
    }

    @Test
    public void testThreadInfo() {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfoArray = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo : threadInfoArray) {
            pringThreadInfo(threadInfo);
        }
    }

    /**
     * ThreadInfo 包含有关线程的信息，包括：
     * <h1>常规线程信息</h1>
     * <li>线程 ID。
     * <li>线程名称。
     * 
     * <h1>执行信息</h1>
     * <li>线程状态。
     * <li>由于以下原因阻塞线程的对象：等待进入同步块/方法，或者等待 Object.wait 方法的通知，或者由于 LockSupport.park
     * 调用而暂停。
     * <li>拥有阻塞线程对象的线程的 ID。
     * <li>线程的堆栈跟踪。
     * <li>线程锁定的对象监视器列表。
     * <li>线程锁定的可拥有同步器列表。
     * 
     * <h1>同步统计数据</h1>
     * <li>由于同步或等待通知而阻塞线程的次数。
     * <li>从启动线程争用监视开始，由于同步或等待通知而阻塞线程的累计时间。某些 Java
     * 虚拟机实现可能不支持此功能。ThreadMXBean.isThreadContentionMonitoringSupported() 方法可用于确定
     * Java 虚拟机是否支持此功能。
     * <p>
     * 此线程信息类设计用于监视系统，不用于同步控制。
     * 
     * @param threadInfo
     */
    public static void pringThreadInfo(ThreadInfo threadInfo) {
        System.out.println("-----------------------------------------------------");
        System.out.println(threadInfo.toString());
        System.out.println("ThreadId = " + threadInfo.getThreadId());
        System.out.println("ThreadName = " + threadInfo.getThreadName());
        System.out.println("ThreadState = " + threadInfo.getThreadState());
        System.out.println("BlockedCount = " + threadInfo.getBlockedCount());// jvm启动以来线程阻塞总次数
        System.out.println("BlockedTime = " + threadInfo.getBlockedTime());// jvm启动以来线程阻塞的总时间
        System.out.println("WaitedCount = " + threadInfo.getWaitedCount());// 线程在WAITING或TIMED_WAITING状态中的次数
        System.out.println("WaitedTime = " + threadInfo.getWaitedTime());// WAITING or TIMED_WAITING state 时间
        System.out.println("isInNative = " + threadInfo.isInNative());// 与线程相关的native方法是否通过了测试
        System.out.println("isSuspended = " + threadInfo.isSuspended());// 与线程相关的线程是否挂起了
        StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
        for (StackTraceElement stackTraceElement : stackTraceElements) {
            System.out.println(stackTraceElement.toString());
        }
    }
}
